﻿using NLog;
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;

namespace SocketHelper
{
    public class Common
    {
        /// <summary>
        /// 日志
        /// </summary>
        private static readonly Logger logger = LogManager.GetCurrentClassLogger();

        /// <summary>
        /// 控制台单行输出，同时生成日志文件
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="level"></param>
        public static void ConsoleM(string msg, int level=0)
        {
            string content = string.Format("{0}-{1}", DateTime.Now, msg);
            switch (level)
            {
                case 0:
                    logger.Debug(msg);
                    break;
                case 1:
                    logger.Info(msg);
                    break;
                case 2:
                    logger.Warn(msg);
                    break;
                case 3:
                    logger.Error(msg);
                    break;
                case 4:
                    logger.Fatal(msg);
                    break;
                default:
                    logger.Debug(msg);
                    break;
            }
            
            Console.WriteLine(content);
            //日后还得加上日志
        }

        public static bool SendFile(string IP, int Port, string fullPath)
        {
            //创建一个文件对象
            FileInfo EzoneFile = new FileInfo(fullPath);
            //打开文件流
            FileStream EzoneStream = EzoneFile.OpenRead();
            //包的大小
            int PacketSize = 10000;
            //包的数量
            int PacketCount = (int)(EzoneStream.Length / ((long)PacketSize));
            //最后一个包的大小
            int LastDataPacket = (int)(EzoneStream.Length - ((long)(PacketSize * PacketCount)));
            //指向远程服务端节点
            IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(IP), Port);
            //创建套接字
            Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //连接到发送端
            try
            {
                client.Connect(ipep);
                Common.ConsoleM("connect...ok!");
            }
            catch
            {
                Common.ConsoleM("连接服务器失败！");
                return false;
            }
            //获得客户端节点对象
            IPEndPoint clientep = (IPEndPoint)client.RemoteEndPoint;
            //发送[文件名]到客户端
            TransferFiles.SendVarData(client, System.Text.Encoding.Unicode.GetBytes("F_" + EzoneFile.Name));
            //发送[包的大小]到客户端
            TransferFiles.SendVarData(client, System.Text.Encoding.Unicode.GetBytes(PacketSize.ToString()));
            //发送[包的总数量]到客户端
            TransferFiles.SendVarData(client, System.Text.Encoding.Unicode.GetBytes(PacketCount.ToString()));
            //发送[最后一个包的大小]到客户端
            TransferFiles.SendVarData(client, System.Text.Encoding.Unicode.GetBytes(LastDataPacket.ToString()));
            bool isCut = false;
            //数据包
            byte[] data = new byte[PacketSize];
            int cnt = 0;
            //开始循环发送数据包
            for (int i = 0; i < PacketCount; i++)
            {
                //从文件流读取数据并填充数据包
                EzoneStream.Read(data, 0, data.Length);
                //发送数据包
                if (TransferFiles.SendVarData(client, data) == 3)
                {
                    isCut = true;
                    return false;
                }
                System.Threading.Thread.Sleep(100);
                Console.WriteLine("                    ");
                Console.SetCursorPosition(0, Console.CursorTop - 1);
                float percent = i * 100 / PacketCount;
                cnt = i;
                Console.Write(DateTime.Now + "-已发送" + cnt + "个包,共有" + PacketCount + "个包");
            }
            //如果还有多余的数据包，则应该发送完毕！
            if (LastDataPacket != 0)
            {
                data = new byte[LastDataPacket];
                EzoneStream.Read(data, 0, data.Length);
                TransferFiles.SendVarData(client, data);
            }
            if (cnt < PacketCount)
            {
                Console.WriteLine("");
                Common.ConsoleM("余量包发送完毕，共计发送" + PacketCount + "个数据包");
            }
            //关闭套接字
            client.Close();
            //关闭文件流
            EzoneStream.Close();
            if (!isCut)
            {
                return true;
            }
            return false;
        }

        public static bool SendMsg(string IP, int Port, string Msg)
        {
            //指向远程服务端节点
            IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(IP), Port);
            //创建套接字
            Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //连接到发送端
            try
            {
                client.Connect(ipep);
                //Common.ConsoleM("connect...ok!");
                TransferFiles.SendVarData(client, System.Text.Encoding.Unicode.GetBytes(Msg));
                while (true)
                {
                    string ret = System.Text.Encoding.Unicode.GetString(TransferFiles.ReceiveVarData(client));
                    if (!string.IsNullOrEmpty(ret))
                    {
                        Common.ConsoleM(ret);
                        break;
                    }
                }
            }
            catch
            {
                Common.ConsoleM("连接服务器失败！");
                return false;
            }
            return true;
        }

        public static void Command_File(string ip, int port)
        {
            Common.ConsoleM(string.Format("进入传输文件模式，服务器地址为{0}，端口为{1}，请输入文件完整路径", ip, port));
            while (true)
            {
                string fullPath = Console.ReadLine();
                if (fullPath == "exit")
                {
                    Common.ConsoleM("已退出文件传输模式");
                    break;
                }
                if (File.Exists(fullPath))
                {
                    Common.ConsoleM("开始传输...");
                    Common.SendFile(ip, port, fullPath);
                    //break;
                }
                else
                {
                    Common.ConsoleM("路径不合法或文件不存在");
                }
            }
        }
    }
}
